package org.systm.adminuser.service;

import org.global.basic.BaseServiceOpImpl;
import org.global.basic.CurdFindRepository;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.systm.adminuser.dao.AdminUserStore;
import org.systm.adminuser.entity.AdminUser;
import org.systm.adminuser.entity.UserPermission;
import org.systm.adminuser.entity.UserRole;
import org.systm.adminuser.params.AdminUserParams;
import org.systm.adminuser.service.condition.AdminUserQuery;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.criteria.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class AdminUserService extends BaseServiceOpImpl<AdminUser, String, AdminUserParams<String>> implements UserDetailsService {
    @Resource
    AdminUserStore adminUserStore;

    @Resource
    UserRoleService userRoleService;

    @Resource
    EntityManager entityManager;

    @Resource
    PasswordEncoder passwordEncoder;

    @Override
    public EntityManager entityManger() {
        return this.entityManager;
    }

    @Override
    public CurdFindRepository<AdminUser, String> repository() {
        return this.adminUserStore;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AdminUser update(AdminUserParams<String> adminUserParams) {
        List<String> rids = adminUserParams.getRids();
        String userId = adminUserParams.getId();
        Objects.requireNonNull(rids, "角色id不能是空");
        Objects.requireNonNull(userId, "用户id不能是空");
        Optional<AdminUser> adminUserOp = findById(userId);
        if (adminUserOp.isEmpty()) throw new RuntimeException("找不到用户");
        AdminUser adminUser = adminUserOp.get();
        Optional<List<UserRole>> rolesOp = userRoleService.findByIds(rids, String.class);
        if (rolesOp.isEmpty()) throw new RuntimeException("找不到角色");
        adminUser.getRoles().addAll(rolesOp.get());
        super.save(adminUserParams);
        return adminUser;
    }

    @Override
    public AdminUser del(AdminUserParams<String> adminUserParams) {
        AdminUser adminUser = super.del(adminUserParams);
        List<UserRole> roles = adminUser.getRoles();
        roles.clear();
        repository().save(adminUser);
        return adminUser;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AdminUser save(AdminUserParams<String> adminUserParams) {
        AdminUser adminUser = adminUserParams.getAdminUser();
        String username = adminUser.getUsername();
        boolean usernameExists = exists(AdminUserQuery.getExistsUsername().apply(username));
        if (usernameExists) throw new RuntimeException("用户名已经存在，请重新输入");
        adminUser.setPassword(passwordEncoder.encode(adminUser.getPassword()));
        adminUser.setSalt(UUID.randomUUID().toString());
        return super.save(adminUserParams);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Optional<AdminUser> optional = findOne(AdminUserQuery.getExistsUsername().apply(username));
        if (optional.isEmpty()) throw new UsernameNotFoundException("账号或者密码错误");
        List<UserRole> roles = optional.get().getRoles();
        Set<UserPermission> authorities = new HashSet<>();
        for (UserRole role : roles) authorities.addAll(role.getPermissions());
        optional.get().setAuthorities(authorities);
        return optional.get();
    }
}
